package com.im.services.handler;

import com.alibaba.fastjson.JSON;
import com.im.services.utils.HttpClientUtils;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.MultiValueMap;
import org.yeauty.annotation.*;
import org.yeauty.pojo.Session;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@ServerEndpoint(
        host = "${websocket.host}"
        , path = "${websocket.path}/{req}",
        port = "${websocket.port}",
        maxFramePayloadLength = Integer.MAX_VALUE + "")
public class TsWebSocketHanlder {

    @Autowired
    private SesssionManager sesssionManager;

    public TsWebSocketHanlder() {
        log.debug("构造器");
    }


    @BeforeHandshake
    public void handshake(Session session, HttpHeaders headers,
                          @RequestParam String req,
                          @RequestParam MultiValueMap reqMap) {
        // 把客户端信息保存到session中
        String token = headers.get("token");
        log.debug("新客户端连接:" + token);
        session.setAttribute("token", token);
    }

    /**
     * 客户带连接时调用
     *
     * @param session
     * @param headers
     * @param req
     * @param reqMap
     * @param arg
     * @param pathMap
     */
    @OnOpen
    public void onOpen(Session session, HttpHeaders headers, @RequestParam String req,
                       @RequestParam MultiValueMap reqMap, @PathVariable String arg,
                       @PathVariable Map pathMap) {
        log.debug("req:{}", req);
        log.debug("arg:{}", arg);
        log.debug("reqMap:{}", reqMap);
        log.debug("Map:{}", pathMap);
        String token = (String) session.getAttribute("token");
        log.debug("token:{}", token);
        log.debug("客户端【" + token + "】连接成功");

        // 连接成功后把登录的用户保存起来
        sesssionManager.add(token, session);

    }

    @OnClose
    public void onClose(Session session) throws IOException {
        String token = session.getAttribute("token");
        log.debug("客户端【" + token + "】关闭");
        sesssionManager.remove(token);
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        log.debug("连接出现问题 {}", throwable.getMessage());
    }

    @OnMessage
    public void onMessage(Session session, String message) {
        log.debug("客户端【" + session.getAttribute("token") + "】发送消息:" + message);


        // 1.把json转转成Map
        Map<String, String> map = JSON.parseObject(message, Map.class);

        // 2.获取数据
        String msg = map.get("msg");
        String toToken = map.get("to").toString();


        if ("gpt".equals(toToken)) {
            Map<String, String> queryMap = new HashMap<>();
            queryMap.put("content",msg);
            Map<String, String> hashMap = new HashMap<>();
            try {
                HttpResponse httpResponse = HttpClientUtils.doPost("http://127.0.0.1:8080", "/send", "POST",
                        hashMap, queryMap, (byte[]) null);
                String s = EntityUtils.toString(httpResponse.getEntity());
                System.out.println("resp:" + s);
                session.sendText(s);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return;
        }

        // 3.找到toTOken的session
        Session toSession = sesssionManager.get(toToken);
        if (toSession == null) {
            session.sendText("【" + toToken + "】不在线");
            return;
        }
        toSession.sendText(msg);
    }

    @OnBinary
    public void onBinary(Session session, byte[] bytes) {
        log.debug("onBinary:{}", bytes);
        session.sendBinary(bytes);
    }

    @OnEvent
    public void onEvent(Session session, Object evt) {
        log.debug("onEvent");
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            switch (idleStateEvent.state()) {
                case READER_IDLE:
                    log.debug("read idle");
                    break;
                case WRITER_IDLE:
                    log.debug("write idle");
                    break;
                case ALL_IDLE:
                    log.debug("all idle");
                    break;
                default:
                    break;
            }
        }
    }
}
